<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>数组深浅拷贝</title>
  </head>
  <body>
    <script>
      /**
       * 深拷贝和浅拷贝是只针对Object和Array这样的对象数据类型的
       * 参考博客：https://www.cnblogs.com/lyt0207/p/12082727.html
       * 参考博客：https://www.cnblogs.com/williamjie/p/11192895.html
       *
       * 浅拷贝和深拷贝的区别：
       * 浅拷贝：仅仅是指向被复制的内存地址，如果原地址发生改变，那么浅复制出来的对象也会相应的改变。
       * 深拷贝：在计算机中开辟一块新的内存地址用于存放复制的对象。
       * 
       * 示例： 假设B复制了A，修改A的时候，看B是否发生变化：
       * 若B改变了，说明是浅拷贝，拿人手短！（修改堆内存中的同一个值）
       * 若B没有改变，说明是深拷贝，自食其力！（修改堆内存中的不同的值）
       */
      
      /**
       * 数组浅拷贝
       * */
      //方法1：扩展运算符：...
      let array = [1, 3, 4, 6];
      let arr22 = [...array];
      console.log("扩展运算符=", arr22);

      //方法2：Object.assign(arr3, array)
      let arr3 = [];
      Object.assign(arr3, array);
      console.log("Object.assign=", arr3);

      //方法3：slice
      let arr4 = array.slice();
      console.log("slice=", arr4);

      //方法4:concat()
      let arr5 = array.concat();
      console.log("concat=", arr5);

      //方法5：_proto_
      let arr6 = [];
      arr6._proto_ = array;
      console.log("_proto_=", arr6);

      /*
       * 深度拷贝实现的原理：
       * 递归方法实现深度克隆原理：遍历对象、数组直到里边都是基本数据类型，然后再去复制，就是深度拷贝
       */
      //定义一个深度克隆函数,target可能是Object(Array、null、RegExp、普通对象)、基本数据类型
      function deepClone(target) {
        //定义一个变量，用来存储克隆的数据
        let result;
        //如果当前深度拷贝是一个对象的话
        if (typeof target === "object") {
          //如果是数组
          if (Array.isArray(target)) {
            result = []; // 将result赋值为一个数组，并且执行遍历
            for (let i in target) {
              //递归克隆数组中的每一项
              result.push(deepClone(target[i]));
            }
          } else if (target === null) {
            //如果是null，直接赋值null
            result = target;
          } else if (target.constructor === "RegExp") {
            //如果当前的值是一个RegExp对象的话，直接赋值
            result = target;
          } else {
            result = {};
            // 否则是普通对象，直接for in循环，递归赋值对象的所有值
            for (let i in target) {
              result[i] = deepClone(target[i]);
            }
          }
        } else {
          // 如果不是对象的话，就是基本数据类型，那么直接赋值
          result = target;
        }
        return result; //返回result
      }

      console.log("深度克隆=", deepClone([1, 2, 3]));
    </script>
  </body>
</html>
